home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 326-350 / disk_327 / msh / src / hanmain.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  10KB  |  456 lines

  1. /*-
  2.  * $Id: hanmain.c,v 1.4 90/01/27 20:13:00 Rhialto Exp $
  3.  * $Log:    hanmain.c,v $
  4.  * Revision 1.4  90/01/27  20:13:00  Rhialto
  5.  * *** empty log message ***
  6.  * 
  7.  * Revision 1.3  89/12/17  21:29:51  Rhialto
  8.  * *** empty log message ***
  9.  *
  10.  * Revision 1.1  89/12/17  20:02:31  Rhialto
  11.  * Initial revision
  12.  *
  13.  *
  14.  *  HANMAIN.C
  15.  *
  16.  *  The code for the messydos file system handler.
  17.  *
  18.  *  Some start/stop stuff that is not really part of the
  19.  *  file system itself but that must be done anyway.
  20.  *
  21.  *  This code is (C) Copyright 1989 by Olaf Seibert. All rights reserved. May
  22.  *  not be used or copied without a licence.
  23. -*/
  24.  
  25. #include "han.h"
  26. #include "dos.h"
  27.  
  28. #ifdef DEBUG
  29. #   define    debug(x)  dbprintf x
  30. #else
  31. #   define    debug(x)
  32. #endif
  33.  
  34. extern char    DotDot[1 + 8 + 3];
  35. struct Library *IntuitionBase;
  36. static char RCSId[] = "Messydos filing system $Revision: 1.4 $ $Date: 90/01/27 20:13:00 $, by Olaf Seibert";
  37.  
  38. byte
  39. ToUpper(ch)
  40. register byte    ch;
  41. {
  42.     if (ch >= 'a' && ch <= 'z')
  43.     return ch + ('A' - 'a');
  44.     if (ch == '.')
  45.     return '!';
  46.     return ch & ~DIR_DELETED_MASK;
  47. }
  48.  
  49. long
  50. lmin(a, b)
  51. long        a,
  52.         b;
  53. {
  54.     return (a < b) ? a : b;
  55. }
  56.  
  57. byte           *
  58. ZapSpaces(begin, end)
  59. register byte  *begin,
  60.            *end;
  61. {
  62.     while (end > begin && end[-1] == ' ')
  63.     *--end = '\0';
  64.  
  65.     return end;
  66. }
  67.  
  68. /*
  69.  * Map an arbitrary file name to MS-DOS conventions. The output format is
  70.  * 8+3 without dot, padded with spaces, suitable for direct comparison
  71.  * with directory entries. Return a pointer to the delimiter found ('\0'
  72.  * or '/'). [[Make sure that Examine/ExNext return a proper inverse of
  73.  * this...]]
  74.  */
  75.  
  76. byte           *
  77. ToMSName(dest, source)
  78. byte           *dest;
  79. register byte  *source;
  80. {
  81.     byte       *dotp;
  82.     byte       *slashp;
  83.     register int    i,
  84.             len;
  85.  
  86.     if (*source == '/') {       /* parentdir */
  87.     strncpy(dest, DotDot, 8 + 3);   /* ".." */
  88.     return source;
  89.     }
  90.     /*
  91.      * Remove any strictly leading dots. .info -> info, .indent.pro ->
  92.      * indent.pro, .profile -> profile, etc.
  93.      */
  94.     while (*source == '.')
  95.     source++;
  96.  
  97.     /*
  98.      * Find dot and slash which are delimiters of name and extension.
  99.      */
  100.     {
  101.     register byte  *cp;
  102.  
  103.     cp = source;
  104.     while (*cp) {
  105.         if (*cp == '.' || *cp == '/')
  106.         break;
  107.         cp++;
  108.     }
  109.     dotp = cp;
  110.     while (*cp) {
  111.         if (*cp == '/')
  112.         break;
  113.         cp++;
  114.     }
  115.     slashp = cp;
  116.     }
  117.  
  118.     len = dotp - source;
  119.     if (len > 8)
  120.     len = 8;
  121.  
  122.     for (i = 0; i < len; i++) {
  123.     *dest++ = ToUpper(*source++);
  124.     }
  125.     for (; i < 8; i++) {
  126.     *dest++ = ' ';
  127.     }
  128.  
  129.     source = dotp + 1;
  130.     len = slashp - source;    /* so will be -1 if no suffix */
  131.     if (len > 3)
  132.     len = 3;
  133.  
  134.     for (i = 0; i < len; i++) {
  135.     *dest++ = ToUpper(*source++);
  136.     }
  137.     for (; i < 3; i++) {
  138.     *dest++ = ' ';
  139.     }
  140.  
  141.     return slashp;
  142. }
  143.  
  144. /*
  145.  * Do the Info call.
  146.  */
  147.  
  148. long
  149. MSDiskInfo(infodata)
  150. struct InfoData *infodata;
  151. {
  152.     extern DEVLIST *VolNode;
  153.  
  154.     setmem(infodata, sizeof (*infodata), 0);
  155.  
  156.     infodata->id_DiskState = IDDiskState;
  157.     infodata->id_DiskType = IDDiskType;
  158.     infodata->id_UnitNumber = UnitNr;
  159.  
  160.     infodata->id_VolumeNode = (BPTR) CTOB(VolNode);
  161.     infodata->id_InUse = LockList ? 1 : 0;
  162.  
  163.     if (IDDiskType == ID_DOS_DISK) {
  164.     infodata->id_NumBlocks = Disk.nsects;
  165.     infodata->id_NumBlocksUsed = Disk.nsects - Disk.nsectsfree;
  166.     infodata->id_BytesPerBlock = Disk.bps;
  167.     }
  168.     return DOSTRUE;
  169. }
  170.  
  171. /*
  172.  * We (re-)establish our List of MSFileLocks after a disk has been
  173.  * (re-)inserted. If there are no known locks, we make the root lock from
  174.  * the volume label, if there is one.
  175.  *
  176.  * We get a special cookie to hand to a cleanup routine that we must call
  177.  * when finally all locks on the current disk are UnLock()ed. (this is
  178.  * actually the volume node, but we don't want to know that.)
  179.  *
  180.  * This must be called some time after IdentifyDisk().
  181.  */
  182.  
  183. void
  184. MSDiskInserted(locks, cookie)
  185. register struct LockList **locks;
  186. void           *cookie;
  187. {
  188.     debug(("MSDiskInserted %08lx\n", cookie));
  189.  
  190.     LockList = *locks;
  191.  
  192.     if (LockList == NULL) {
  193.     LockList = NewLockList(cookie);
  194.     RootLock = MakeLock(NULL, &Disk.vollabel, SHARED_LOCK);
  195.     } else {
  196.     RootLock = MSDupLock(GetTail(&LockList->ll_List));
  197.     }
  198.  
  199.     InitCacheList();
  200. }
  201.  
  202. /*
  203.  * Remove the current disk. A place is offered to save the current
  204.  * LockList to restore later. We must unlock the root lock since it isn't
  205.  * a real reference to the disk, just a placeholder for dummies that hand
  206.  * us NULL locks.
  207.  */
  208.  
  209. int
  210. MSDiskRemoved(locks)
  211. register struct LockList **locks;
  212. {
  213. #ifndef READONLY
  214.     if (FatDirty || (DelayState & DELAY_DIRTY))
  215.     MSUpdate(1);            /* Force a requester */
  216. #endif
  217.  
  218.     FreeFat();
  219.     FreeCacheList();
  220.  
  221.     IDDiskType = ID_NO_DISK_PRESENT;
  222.     *locks = NULL;
  223.  
  224.     if (RootLock == NULL) {
  225.     debug(("MSDiskRemoved with no RootLock\n"));
  226.     return 1;
  227.     }
  228. #ifdef DEBUG
  229.     if (RootLock != GetTail(&LockList->ll_List)) {
  230.     debug(("RootLock not at end of LockList!\n"));
  231.     /* Get the lock on the root dir at the tail of the List */
  232.     Remove(RootLock);
  233.     AddTail(&LockList->ll_List, RootLock);
  234.     }
  235. #endif
  236.  
  237.     /*
  238.      * If there are no real locks on the disk, we need not keep any
  239.      * information about it.
  240.      */
  241.  
  242.     MSUnLock(RootLock);         /* may call FreeLockList and free VolNode
  243.                  * (!) */
  244.     RootLock = NULL;
  245.  
  246.     if (LockList) {
  247.     *locks = LockList;    /* VolNode can't be gone now... */
  248.     LockList = NULL;
  249.     return 0;        /* not all references gone */
  250.     } else {
  251.     return 1;        /* all gone, even the VolNode */
  252.     }
  253. }
  254.  
  255. void
  256. HanCloseDown()
  257. {
  258. #ifdef DEBUG
  259.     register struct MSFileLock *fl;
  260.  
  261.     while (LockList && (fl = (struct MSFileLock *) GetHead(&LockList->ll_List))) {
  262.     debug(("UNLOCKING %08lx: ", fl));
  263.     PrintDirEntry(&fl->msfl_Msd);
  264.     MSUnLock(fl);           /* Remove()s it from this List */
  265.     }
  266. #endif
  267.     if (DiskIOReq) {
  268.     if (DiskIOReq->iotd_Req.io_Unit) {
  269.         MSUpdate(1);
  270.         CloseDevice(DiskIOReq);
  271.     }
  272.     DeleteExtIO(DiskIOReq);
  273.     DiskIOReq = NULL;
  274.     }
  275.     if (TimeIOReq) {
  276.     if (TimeIOReq->tr_node.io_Unit) {
  277.         WaitIO(TimeIOReq);
  278.         CloseDevice(TimeIOReq);
  279.     }
  280.     DeleteExtIO(TimeIOReq);
  281.     TimeIOReq = NULL;
  282.     }
  283.     if (DiskReplyPort) {
  284.     DeletePort(DiskReplyPort);
  285.     DiskReplyPort = NULL;
  286.     }
  287.     if (IntuitionBase) {
  288.     CloseLibrary(IntuitionBase);
  289.     IntuitionBase = NULL;
  290.     }
  291. }
  292.  
  293. int
  294. HanOpenUp()
  295. {
  296.     LockList = NULL;
  297.     RootLock = NULL;
  298.     Fat = NULL;
  299.     IDDiskState = ID_WRITE_PROTECTED;
  300.     IDDiskType = ID_NO_DISK_PRESENT;
  301.     DelayState = DELAY_OFF;
  302.     Disk.bps = MS_BPS;
  303.     InitCacheList();
  304.  
  305.     TimeIOReq = NULL;
  306.  
  307. #ifdef DEBUG
  308.     if (!(DiskReplyPort = CreatePort("MSH:disk.replyport", -1L)))
  309.     goto abort;
  310. #else
  311.     if (!(DiskReplyPort = CreatePort(NULL, -1L)))
  312.     goto abort;
  313. #endif
  314.  
  315.     debug(("DiskReplyPort = 0x%08lx\n", DiskReplyPort));
  316.  
  317.     if (!(DiskIOReq = CreateExtIO(DiskReplyPort, (long) sizeof (*DiskIOReq)))) {
  318.     debug(("Failed to CreateExtIO\n"));
  319.     goto abort;
  320.     }
  321.     if (OpenDevice(DevName, UnitNr, DiskIOReq, DevFlags | TDF_ALLOW_NON_3_5)) {
  322.     debug(("Failed to OpenDevice\n"));
  323.     goto abort;
  324.     }
  325.     TimeIOReq = (struct timerequest *) CreateExtIO(DiskReplyPort,
  326.                          (long) sizeof (*TimeIOReq));
  327.  
  328.     if (TimeIOReq == NULL || OpenDevice(TIMERNAME, UNIT_VBLANK, TimeIOReq, 0L))
  329.     goto abort;
  330.     TimeIOReq->tr_node.io_Flags = IOF_QUICK;    /* For the first WaitIO() */
  331.  
  332.     IntuitionBase = OpenLibrary("intuition.library", 0L);
  333.     return DOSTRUE;
  334.  
  335. abort:
  336.     HanCloseDown();
  337.     return 0;
  338. }
  339.  
  340. /*
  341.  * Relabel the disk. We create new labels if necessary.
  342.  */
  343.  
  344. long
  345. MSRelabel(newname)
  346. byte           *newname;
  347. {
  348. #ifdef READONLY
  349.     return DOSFALSE;
  350. #else
  351.     /*
  352.      * A null or empty string means: remove the label, if any.
  353.      */
  354.     if (!newname || !*newname) {
  355.     if ((int) RootLock->msfl_DirSector >= (int) Disk.rootdir) {
  356.         RootLock->msfl_Msd.msd_Name[0] = DIR_DELETED;
  357.         RootLock->msfl_Msd.msd_Attributes = 0;
  358.         WriteFileLock(RootLock);
  359.         RootLock->msfl_Msd = FakeRootDirEntry.de_Msd;
  360.         RootLock->msfl_DirSector = -1;
  361.         Disk.vollabel = FakeRootDirEntry;
  362.     }
  363.     return DOSTRUE;
  364.     }
  365.     /*
  366.      * No label yet? Then we must create one, even if we need to move
  367.      * something else for it.
  368.      */
  369.  
  370.     if ((int) RootLock->msfl_DirSector < 0) {
  371.     struct MSFileLock *new;
  372.  
  373.     new = MSLock(RootLock, "><>.\\", EXCLUSIVE_LOCK ^ MODE_CREATEFILE);
  374.     if ((new == NULL) && (new = EmptyFileLock)) {
  375.         error = 0;
  376.         if (new->msfl_DirSector == Disk.rootdir) {
  377.         RootLock->msfl_DirSector = Disk.rootdir;
  378.         RootLock->msfl_DirOffset = new->msfl_DirOffset;
  379.         } else {
  380.         /*
  381.          * Move something out of the first directory block. Try
  382.          * not to move system files or directories (. ..), but
  383.          * we'll do it if we need to. Set the root dir date to
  384.          * now.
  385.          */
  386.         byte           *fromsec;
  387.         byte           *tosec;
  388.         register struct MsDirEntry *dir;
  389.  
  390.         fromsec = GetSec(Disk.rootdir);
  391.         tosec = GetSec(new->msfl_DirSector);
  392.  
  393.         dir = (struct MsDirEntry *) fromsec;
  394.         while (dir->msd_Attributes & (ATTR_SYSTEM | ATTR_DIRECTORY)) {
  395.             if ((byte *) ++dir >= fromsec + Disk.bps) {
  396.             --dir;    /* Back to last entry in the block */
  397.             break;    /* and move it no matter what */
  398.             }
  399.         }
  400.         CopyMem(dir, tosec + new->msfl_DirOffset,
  401.             (long) sizeof (struct MsDirEntry));
  402.         MarkSecDirty(tosec);
  403.         RootLock->msfl_DirSector = Disk.rootdir;
  404.         RootLock->msfl_DirOffset = (byte *) dir - fromsec;
  405.  
  406.         FreeSec(tosec);
  407.         FreeSec(fromsec);
  408.  
  409.         }
  410.     }
  411.     EmptyFileLock = NULL;
  412.     MSUnLock(new);
  413.     }
  414.     if ((int) RootLock->msfl_DirSector >= Disk.rootdir) {
  415.     struct DateStamp dateStamp;
  416.  
  417.     /*
  418.      * The easy part: Copy the name to Disk.vollabel and RootLock.
  419.      */
  420.     {
  421.         register int    i;
  422.         register byte  *s,
  423.                *d;
  424.  
  425.         s = newname;
  426.         d = Disk.vollabel.de_Msd.msd_Name;
  427.         for (i = 0; i < 8 + 3; i++) {
  428.         if (s[0])
  429.             *d++ = ToUpper(*s++);
  430.         else
  431.             *d++ = ' ';
  432.         }
  433.     }
  434.     DateStamp(&dateStamp);
  435.     ToMSDate(&Disk.vollabel.de_Msd.msd_Date,
  436.          &Disk.vollabel.de_Msd.msd_Time, &dateStamp);
  437.     RootLock->msfl_Msd = Disk.vollabel.de_Msd;    /* Just for the name and
  438.                              * date */
  439.     WriteFileLock(RootLock);
  440.  
  441.     return DOSTRUE;
  442.     }
  443.     return DOSFALSE;
  444. #endif
  445. }
  446.  
  447. #ifdef DEBUG
  448.  
  449. _abort()
  450. {
  451.     HanCloseDown();
  452.     RemTask(NULL);
  453. }
  454.  
  455. #endif                /* DEBUG */
  456.